Syntax and Style Guidlines


code is read much more often than it is written -- Guido's key insights

One of the main features of Python is properly formatted code, as not properly formatted will always result in invalid code. Removing the need for block markers, such as curly brackets '{}' which are so commonly used in most of the languages such as C/C++ & Java, instead of spaces/ tab, results in properly formatted code

In this section, we will be discussing major points of language syntax such as comments, blocks multi-line code and introduction to PEP 8.

Blocks


In python, indentations instead of using curly brackets "{", are used to define the code blocks. Indentations can be in the form of either space(s) or tab(s).

NOTE

  • Indentations consistency should be maintained throughout the project and please avoid mixing tabs and spaces.
  • The official recommendation coding style (http://www.python.org/dev/peps/pep-0008/) is to use four spaces for indentation and this convention is widely accepted by developers.
  • Also, for similar reasons, please use one IDE throughout the project, if in doubt

The line before the block always ends with a colon (:) and is a control structure of the language or a statement of a new structure (a function, a class for example).

Code layout

Lines and Indentation

Python doesn't use braces '{}', as most programming languages use, to mark blocks of code for classes, function definitions and flow controls. Blocks of code are denoted by grouped indentation, which is rigidly enforced.

The code block should be marked by the same number of spaces in the indentation, such as if four spaces or a tab is used, then it should be consistent for the entire project.

Example:


In [1]:
if True:
    print("Welcome")
else:
    print("Sayonara")


Welcome

In [1]:
if True:
            print("Guten Morgen!")
else:
            print("Gute Nacht!")


Guten Morgen!

In [ ]:

In the example given above, we have uniform four&eight spaces respectively and in both examples, the code worked without any issue. You will also note that in the second example the code is not very readable and the first example it's readable. So, please choose count of spaces which suits your need.

!!! NOTE !!!:

One can choose any number of spaces from 1 - inifinity but have to stick to them, most commonly used spaces are 2 or 4.

Execution of below block of code will result in error as the indentation level is not uniform. In line 5 we have few extra spaces without any cause, hence the code will fail to execute.


In [3]:
if (True):  
    print("True") 
else:  
    print("Test")
       print("False")


  File "<ipython-input-3-155005a566f3>", line 5
    print("False")
    ^
IndentationError: unexpected indent

Lets fix the above issue, by setting the indentation and execute the code again


In [2]:
if True:
    print("Answer")
    print("True")
else:
    print("Question")
    print("False")


Answer
True

For those C/C++/Java developers who are not initially comfortable without { can also use #{ #} pair, as shown in the example below, to denote the starting block and ending blocks.


In [3]:
if True: #{
    print("Answer")
    print("True")
#}
else: #{
    print("Question")
    print("False")
#}


Answer
True

Comments

The character # marks the beginning of a comment. Any text after the # will be ignored until the end of the line, with the exception of functional comments.

Functional comments are used to:

  • change the encoding of the source file of the program by adding a comment with the text # - * - coding: <encoding> - # - at the beginning of the file, in which <encoding> is the file encoding (usually latin1 or utf-8). Changing encoding is required to support characters that are not part of the English language, in the source code of the program.
  • define the interpreter that will be used to run the program on UNIX systems, through a comment starting with #! at the beginning of the file, which indicates the path to the interpreter (usually the comment line will be something like #!/usr/bin/env python ).

Block Comments

Block comments generally apply to some (or all) code that follows them, and are indented to the same level as that code. Each line of a block comment starts with a # and a single space (unless it is indented text inside the comment).

Paragraphs inside a block comment are separated by a line containing a single # .

# Date: 
# Time:
# Author:
# Method Name:
# Description:

Inline Comments

An inline comment is a comment statement on the same line as a code statement and they are usually separated by at least two spaces from the statement and should start with a # and a single space.

Inline comments are unnecessary and in fact distracting if they state the obvious. Don't do this:

x = x + 1                 # Increment x

But sometimes, it is useful as shown below:

x = x + 1                 # Compensate for border

Tips for Comments


  • Comments that contradict the code are worse than no comments. Always make a priority of keeping the comments up-to-date when the code changes!
  • Comments should be complete sentences. If a comment is a phrase or sentence, its first word should be capitalized, unless it is an identifier that begins with a lower case letter (never alter the case of identifiers!).
  • If a comment is short, the period at the end can be omitted. Block comments generally consist of one or more paragraphs built out of complete sentences, and each sentence should end in a period.
  • You should use two spaces after a sentence-ending period.
  • When writing English, follow Strunk and White.
  • Python coders from non-English speaking countries: please write your comments in English, unless you are 120% sure that the code will never be read by people who don't speak your language.

In [5]:
#!/usr/bin/env python

# A code line that shows the result of 7 times 3
# A CODE LINE THAT SHOW THE RESULT OF 7 TIMES 3 (BAD Comments)

print (7 * 3) # This is also a comment
"""
This is a multi
line comment / String
"""
st = '''
This is a multi line 

String
"With me"
'
'
'''
print(st)


21

This is a multi line 

String
"With me"
'
'

Indentation

  • Use 4 spaces per indentation level
  • If your code has continuation lines, then they should align wrapped elements either vertically using Python''s implicit line joining inside parentheses, brackets and braces, or using a hanging indent.
  • When using a hanging indent the following should be considered; there should be no arguments on the first line and further indentation should be used to clearly distinguish itself as a continuation line.

In [1]:
# More indentation included to distinguish this from the rest.
def long_function_name(
        var_one, var_two, var_three,
        var_four):
    print(var_one)
    
# Aligned with opening delimiter.
foo = long_function_name("var_one", "var_two",
                         "var_three", "var_four")


# Hanging indents should add a level.
foo = long_function_name(
    "var_one", "var_two",
    "var_three", "var_four")


var_one
var_one

Tabs or Spaces?

"""" Spaces are the preferred indentation method """"

Tabs should be used solely to remain consistent with code that is already indented with tabs.

Python 3 disallows mixing the use of tabs and spaces for indentation.

Maximum Line Length


  • Limit all lines to a maximum of 79 characters.

  • For flowing long blocks of text with fewer structural restrictions (docstrings or comments), the line length should be limited to 72 characters.

  • Limiting the required editor window width makes it possible to have several files open side-by-side, and works well when using code review tools that present the two versions in adjacent columns.

  • The default wrapping in most tools disrupts the visual structure of the code, making it more difficult to understand. The limits are chosen to avoid wrapping in editors with the window width set to 80, even if the tool places a marker glyph in the final column when wrapping lines. Some web based tools may not offer dynamic line wrapping at all.

  • Some teams strongly prefer a longer line length. For code maintained exclusively or primarily by a team that can reach agreement on this issue, it is okay to increase the nominal line length from 80 to 100 characters (effectively increasing the maximum length to 99 characters), provided that comments and docstrings are still wrapped at 72 characters.

  • The Python standard library is conservative and requires limiting lines to 79 characters (and docstrings/comments to 72).

  • The preferred way of wrapping long lines is by using Python's implied line continuation inside parentheses, brackets and braces. Long lines can be broken over multiple lines by wrapping expressions in parentheses. These should be used in preference to using a backslash for line continuation.

  • Backslashes may still be appropriate at times. For example, long, multiple with -statements cannot use implicit continuation, so backslashes are acceptable:


In [ ]:
with open('/path/to/some/file/you/want/to/read') as file_1, \
     open('/path/to/some/file/being/written', 'w') as file_2:
    file_2.write(file_1.read())

Multiline code


In Python, multi-line code is supported by using the backslash character (\) at the end of the line or parentheses, brackets or braces in expressions that use such characters.

Examples of broken lines:


In [10]:
# A line broken by backslash
a = 7 * 3 + \
5 / 2


# A list (broken by comma)
b = ['a', 'b', 'c', 
'd', 'e']

# A function call (broken by comma)
c = range(1,
        11)

# Prints everything
print(a, b, c)


23.5 ['a', 'b', 'c', 'd', 'e'] range(1, 11)

In [14]:
# For i on the list 234, 654, 378, 798:
for i in [234, 654, 378, 798]:
    # If the remainder dividing by 3 is equal to zero:
    if i % 3 == 0: #{
       # Prints...
        print (i, '/ 3 =', i / 3)
    #}


234 / 3 = 78.0
654 / 3 = 218.0
378 / 3 = 126.0
798 / 3 = 266.0

The operator % computes the modulus (remainder of division).

The closing brace/bracket/parenthesis on multi-line constructs may either line up under the first non-whitespace character of the last line of list, as in:


In [4]:
def func(x,y,z,m,n,r):
    print(x,y,z,m,n,r)

my_list = [
    1, 2, 3,
    4, 5, 6
    ]
result = func(
    'a', 'b', 'c',
    'd', 'e', 'f'
    )


a b c d e f

or it may be lined up under the first character of the line that starts the multi-line construct, as in:


In [9]:
def some_function_that_takes_arguments(a1,a2,a3,a4,a5,a6):
    pass

my_list = [
    1, 2, 3,
    4, 5, 6,
]
result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f'
)

line break before or after a binary operator


Donald Knuth explains the traditional rule in his Computers and Typesetting series: "Although formulas within a paragraph always break after binary operations and relations, displayed formulas always break before binary operations".

Following the tradition from mathematics usually results in more readable code:


In [ ]:
# Yes: easy to match operators with operands
income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

In [ ]:
# No: Not easy to match operators with operands
income = (gross_wages +
          taxable_interest +
          (dividends - qualified_dividends) -
          ira_deduction -
          student_loan_interest)

In Python code, it is permissible to break before or after a binary operator, as long as the convention is consistent locally.

For new code Knuth's style is suggested.

Blank Lines


  • Surround top-level function and class definitions with two blank lines.
  • Method definitions inside a class are surrounded by a single blank line.
  • Extra blank lines may be used (sparingly) to separate groups of related functions. Blank lines may be omitted between a bunch of related one-liners (e.g. a set of dummy implementations).
  • Use blank lines in functions, sparingly, to indicate logical sections.
  • Python accepts the control-L (i.e. ^L) form feed character as whitespace; Many tools treat these characters as page separators, so you may use them to separate pages of related sections of your file. Note, some editors and web-based code viewers may not recognize control-L as a form feed and will show another glyph in its place.

Imports


Imports should usually be on separate lines, e.g.:


In [6]:
# Yes: 
import os
import sys

# No:  
import sys, os

# It's okay to say this though:
from subprocess import Popen, PIPE

#from abc import Popen

from subprocess import * # BIG NO

In [9]:
from os import * # -> xyz
from sys import * # -> xyz

In [ ]:
# from os import xyz as os_xyz
# from sys import xyz as sys_xyz

Imports should be grouped in the following order:

  • standard library imports
  • related third party imports
  • local application/library specific imports

blank line between each group of imports is advised.

References